
/*****************************************************************//**
 * \file   rt_os.h
 * \brief  
 * 这里说明一下这个操作系统的运行原理：
 首先，这个框架使用的是纯C语言，不涉及底层，所以无法实现一般操作系统中的“函数中断”，也无法实现时间片。
 
 每个任务都必须运行完了才能执行下一个任务。在任务切换的时候，会像函数返回一样把上次任务的堆栈退出。
 
 这本质上还是一个裸机系统，只是在这个裸机上搭建了一个框架，使其在某些方面可以接近操作系统。
 
 比如，在任务调度，空闲任务统计CPU利用率，各个任务状态，任务休眠函数（虽然任务只能在退出的时候进行休眠）等等。
 
 中断函数里不放链表操作函数，这样就可以保证每次只有一个函数在操作链表。
 
 修改当前运行的任务的优先级并不会立即退出当前的任务，而是等这次任务函数退出后，新的优先级才起作用。
 
 任务挂起只是把任务插入阻塞表，并不会立即终止任务函数，而是会等这次任务函数退出后再转入其他任务。
 
 休眠函数，会等当前的任务函数执行完成，退出函数后才进行休眠。
 
 总的来说，这个操作系统脱离了底层，会有一些滞后性。

 * \author admin
 * \date   August 2022
 *********************************************************************/




#ifndef RTOS_H_
#define RTOS_H_



//os操作系统头文件

#include"stl_dlist.h"  //需要用到双向队列

#include"mcu_.h"  // 系统需要获取时间


#define CPU_Refresh_Interval_ms  10000 //10秒对应的毫秒数,10000毫秒。


//任务抽象一下就只有下面几种操作：初始化，挂起，恢复，休眠，修改优先级，退出任务。
//系统运行时不断从就绪表中提取任务。

//任务状态
#define  TaskStatus_Default         0x00u    /* 初始化的默认值                                */
#define  TaskStatus_Running         0x01u    /* 运行中               任务正在运行             */
#define  TaskStatus_Ready           0x02u    /* Ready to run         任务已就绪               */
#define  TaskStatus_Sleep           0x04u    /* Task is sleeping     任务在休眠               */
#define  TaskStatus_Suspend         0x08u    /* Task is suspended    任务挂起（等待事件发生） */
#define  TaskStatus_Dead            0x10u    /* Task is exit         任务已经退出             */

/// <summary>
/// 错误代码。系统函数运行错误的返回值。
/// </summary>
typedef unt8 error_code;  

#define OS_IDLE_TASK_PRIO 0u      //空闲任务的优先级。0级，最低级，数字越大，优先级越高。其他任务的优先级不允许跟空闲任务一样。
#define OS_IDLE_TASK_ID   0u      //空闲任务的id号

typedef void (*func)(void);  //任务的函数指针。


/// <summary>
/// 任务信息的结构体。用于统计任务的cpu占用率等信息。每CPU_Refresh_Interval_ms更新一次统计信息。
/// </summary>
typedef struct tcb_msg_ {
    /// 这里machineTime_ms以CPU_Refresh_Interval_ms的间隔递增
    unt32 machineTime_ms;     
    /// 上一个CPU_Refresh_Interval_ms任务使用了多少毫秒。
    unt16 timeUsed_ms;        
    /// 最近CPU_Refresh_Interval_ms任务调用的次数。
    unt16 callTimes;          
    /// 最近CPU_Refresh_Interval_ms累计任务调用的延迟时间。（即任务在就绪表等待的时间）
    unt16 callDelay_ms;       
    /// 用于计数当前的CPU_Refresh_Interval_ms中使用的时间。
    unt16 timeUsed_msCount;   
    /// 当前的CPU_Refresh_Interval_ms任务调用的次数。
    unt16 callTimesCount;     
    /// 当前的CPU_Refresh_Interval_ms累计任务调用的延迟时间。（即任务在就绪表等待的时间）
    unt16 callDelay_msCount;  
}TCB_MSG;

 //TASK CONTROL BLOCK 任务控制块
typedef struct os_tcb_ {
    /// 指向链表节点的指针
    DListNode       node;
    /// 任务的函数指针
    func            funcPoint;
    /// 任务时间间隔。则每隔timeInterval毫秒执行一次任务。（本质上是尽量每秒执行1000/timeInterval_ms次）
    int             timeInterval_ms;
    /// 任务优先级
    unt8              priority;
    /// 任务状态
    unt8              status;
    /// 任务id号，调试的时候方便定位是哪个任务出问题。
    unt8              id;
    /// 最近一次任务调用任务使用的时间（单位毫秒）
    unt16             timeUsed_ms;
    /// 任务休眠结束的时间（醒来的时间）（单位毫秒）
    unt32             timeWakeUp_ms;
    /// 任务的统计信息
    TCB_MSG         msg;
} OS_TCB;


/////////////////////////////////////////////////////////////////////////////////////////////////


/// <summary>
/// 允许运行中动态更改任务的优先级。
/// </summary>
/// <param name="tcb">需要修改优先级的任务</param>
/// <param name="new_prio">新的优先级</param>
/// <returns>错误码</returns>
error_code os_task_change_prio(OS_TCB* tcb, unt8 new_prio);

/// <summary>
/// 调用此函数去挂起一个任务。如果tcb是null，挂起当前的任务。
/// </summary>
/// <param name="tcb">要挂起的任务。空闲任务不能被挂起</param>
/// <returns>错误码</returns>
error_code  os_task_suspend(OS_TCB* tcb);

/// <summary>
/// 调用此函数以恢复先前挂起的任务，将挂起的任务插入就绪表
/// </summary>
/// <param name="tcb">请求恢复的任务</param>
/// <returns>错误码</returns>
error_code  os_task_resume(OS_TCB* tcb);

/// <summary>
/// 将任务进入休眠态。
/// 在任务函数运行中调用它来休眠，任务并不会立即休眠，而是等任务函数退出后再进入休眠状态。
/// </summary>
/// <param name="tcb">要休眠的任务。空闲任务不能休眠。</param>
/// <param name="ticks">任务休眠的时间。如果任务已经在休眠，则刷新休眠时间，以睡得久的时间为准</param>
/// <returns>错误码</returns>
error_code os_sleep_ms(OS_TCB* tcb, unt16 ticks);

/// <summary>
/// 创建任务。
/// </summary>
/// <param name="tcb">用户创建的任务地址。</param>
/// <param name="task">任务函数指针</param>
/// <param name="task_prio">任务优先级</param>
/// <param name="identity">任务id号</param>
/// <param name="timeInterval">任务执行间隔。注意：如果任务休眠的时间比执行间隔短，则休眠不会起效果。</param>
/// <returns>错误码</returns>
error_code os_task_create(OS_TCB* tcb, void (*task)(void), unt8 task_prio, unt8 identity, int timeInterval);

/// <summary>
/// 退出任务
/// </summary>
/// <param name="tcb">退出的任务。如果tcb是null，则退出当前运行的任务</param>
void os_task_exit(OS_TCB* tcb);

/// <summary>
/// 用户定义空闲任务
/// </summary>
/// <param name="idle_func">用户定义的空闲任务</param>
void os_user_idle(func idle_func);

/// <summary>
/// 操作系统初始化。主要是初始化任务链表，创建空闲任务。
/// </summary>
/// <param name=""></param>
void os_init(void);

/// <summary>
/// 系统运行函数。一旦进入，就会等系统运行了ms_48Day后再退出。中间会执行任务调度，不断从就绪表中提取函数。
/// </summary>
void os_running(void);







//下面是error_code的取值。
#define OS_no_error                       00u   //无异常
#define OS_unknown                        01u   //未知错误

//insert_list_ready函数的错误
#define OS_insReady_task_is_ready         10u    //任务已经是就绪态了
#define OS_insReady_task_is_running       11u    //任务正在运行中
#define OS_insReady_task_is_dead          12u    //任务已经退出了

//insert_list_sleep函数的错误
#define OS_insSleep_task_is_sleep         21u    //任务已经是休眠态了
#define OS_insSleep_task_is_suspend       22u    //任务已经挂起了
#define OS_insSleep_task_is_dead          23u    //任务已经退出了

//insert_list_suspend函数的错误
#define OS_insSuspend_task_is_suspend     31u    //任务已经是阻塞态了
#define OS_insSuspend_task_is_dead        33u    //任务已经退出了

//os_task_create函数的错误
#define OS_cannot_create_new_task         03u

//os_task_change_prio函数的错误
#define OS_changePrio_prio_is_invalid     41u   //修改优先级，优先级不合法
#define OS_changePrio_task_is_dead        42u   //修改优先级，任务已退出
#define OS_changePrio_task_is_idle        43u   //修改空闲任务的优先级

//os_task_suspend，os_task_resume函数的错误
#define OS_task_suspend_IDLE             50u    //试图挂起空闲任务
#define OS_task_suspend_isSuspended      51u    //任务已挂起
#define OS_task_resume_taskNotSuspended  52u    //想要恢复的任务没被挂起

//os_sleep_ms函数的错误
#define OS_sleep_idle                     62u   //试图休眠空闲任务
#define OS_sleep_sleeping                 62u   //任务已经休眠
#define OS_sleep_suspend                  63u   //任务已经阻塞，不能休眠
#define OS_sleep_dead                     64u   //任务已经退出。

#endif




//









